--[[ Copyright 2012, Chris Ho                               ]]--
--[[ MIT License (Please read the LICENSE file for details) ]]--

Use("common/Const");
Use("common/Log");
Use("common/Task");
Use("common/Pet");
Use("common/Skill");
Use("tasks/Charge");

-- I am a Tier 2 Archer.
local name = "A02";
local Initialize, status = loadfile(PERSONALITY_ARCHER);
Info(name .. ": trying archer personality");
if (Initialize == nil) then
  Info(name .. ": trying default personality (" .. status .. ")");
  Initialize, status = loadfile(PERSONALITY_DEFAULT);
  if (Initialize == nil) then
    Alert(name .. ": " .. status);
    return ME;
  end
end

-- Initialize base personality.
--local instance = Initialize(...);
--local instance = Initialize(arg[1]);
local instance = Initialize();



--[[ React to the current situation ]]--
-- If we lose our target, try to cast sight.
function instance:React()
  Persona.React(self);

  -- Check the target after other reactions complete. (Reactions may
  -- alter the current target.)
  if (self.target ~= 0) then
    -- Sight lasts for 10 seconds. Cast sight at intervals of its duration.
    -- MINIMUM SP: 10 for Sight (Level 1)
    if ((GetV(V_MOTION, self.target) < 0) and (self.timer:MeasureRemaining() < 0) and (GetV(V_SP, self.id) > 10)) then
      -- Use the sight skill on yourself.
      self.task = Do.Create(self, Skill.Create(self.id, SKILL_SIGHT, 1), self.id);

      -- Update the timer (10 seconds, adjusted by tranquility).
      self.timer = Countdown.Create(10000 * self:GetTranquility());
    end
  end
end

--[[ Select an attack for this target ]]--
-- If multiple foes are near this target, then use Arrow Shower!
function instance:Attack(_target)
  -- Calculate the target's preferability.
  local score = self:RateArea(Position.Find(_target), 2);
  local sp = GetV(V_SP, self.id);

  -- Adjust the score based on tranquility.
  score = score * score / self:GetTranquility();

  -- MINIMUM SP: 15 for Arrow Shower
  if (sp >= 15) then
    -- Use more SP if the score is high.
    if ((sp * score) > self.maxsp) then
      -- Use an arrow shower to clear the crowded area.
      self.target = _target;
      self.task = Bombard.Create(self, Skill.Create(self.id, SKILL_ARROWSHOWER, 2), Position.Find(_target));
      Info(name .. ": Chose area skill " .. self.task.skill.code .. " level " .. self.task.skill.level .. " for " .. _target .. " (neighbors " .. neighbors.n .. ", score=" .. score .. ")");
      return;
    end
  end

  -- Use regular attacks for other cases.
  self.target = _target;
  self.task = Charge.Create(self, Skill.None(self.id), self.target);
end

--[[ The pet should help the given target ]]--
-- We cast Sight (our only support skill).
function instance:Help(_target)
  local threat = self:SelectTarget(Creature.Create(_target):Scan(ACTORS));

  -- If nobody is attacking this target, then see if this target is
  -- attacking something.
  if (threat == 0) then threat = GetV(V_TARGET, _target) end
  if (threat ~= 0) then
    -- If any threats are valid, we will assist with an attack.
    self:Attack(threat)
  else
    -- If no offensive support is necessary, then try a support skill.
    -- MINIMUM SP: 10 for Sight (Level 1)
    if (GetV(V_SP, self.id) > 10) then
      -- Use the sight skill on yourself.
      self.task = Do.Create(self, Skill.Create(self.id, SKILL_SIGHT, 1), self.id);

      -- Update the timer (10 seconds, adjusted by tranquility).
      self.timer = Countdown.Create(10000 * self:GetTranquility());
    end
  end
end

--[[ Override Default Rating Calculation ]]--
-- Archers are more range-sensitive, and must consider their
-- own survival as a higher priority.
function instance:RateTarget(_id)
  local there = Position.Find(_id);
  local score = Archer.RateTarget(self, _id);

  -- Tier 2 archers also consider the target's regional preference (for
  -- Arrow Shower).
  score = score + self:RateArea(there, 2);

  return score;
end

Info(name .. " Loaded");
return instance;
